📋

# v2.0 변경 보고서

오른쪽 전용 센서 삭제 · 전방 센서 회전 스캔(rotateRight/Left) 도입 · 장애물 회피 방향 좌측 우선 적용

✚ 추가 87건 ✕ 삭제 25건 ~ 변경 66건 📄 16개 파일
CLAUDE.md

# 프로젝트 설정

✚ 추가 3건✕ 삭제 0건~ 변경 1건합계 4건

구분 | 변경 내용
--- | ---
추가 | 추가 v2.0 작업 지시 사항
추가 | 추가 오른쪽 전용 센서는 존재하지 않는다. 우측 장애물 감지는 전방 센서를 이용한 회전 스캔으로 대체한다.
변경 | 변경 장애물 회피 시 좌/우 방향은 랜덤으로 선택한다 → 장애물 회피 시 좌측을 우선으로 선택한다. 좌측이 막힌 경우에만 우측으로 전환한다.
추가 | 추가 변경 이력

arch/requirements/fr-nfr.md

# 기능/비기능 요구사항

~ 변경 4건합계 4건

구분 | 변경 내용
--- | ---
변경 | 입력: 변경 전방 장애물 감지 신호 (장애물 센서) 전방 장애물 감지 신호 (전방 센서); 우측 여유 공간 감지 (전방 센서 회전 스캔으로 대체, 우측 전용 센서 없음); 좌측 여유 공간 감지 (좌측 센서)
변경 | 선택 정책: 변경 좌/우 모두 여유 있으면 랜덤으로 방향을 선택한다 좌측을 우선으로 선택한다. 좌측이 막힌 경우에만 우측으로 선택한다.
변경 | 입력: 변경 전방·좌·우 장애물 감지 신호 동시 수신 전방·좌측 장애물 감지 신호 동시 수신 (우측 장애물 감지는 전방 센서 회전 스캔으로 대체, 우측 전용 센서 없음)
변경 | 선택 정책: 변경 후진 중 좌/우 모두 동시에 여유 공간이 확보되면 랜덤으로 방향을 선택한다 후진 중 좌/우 여유 공간이 확보되면 좌측을 우선으로 선택한다. 좌측이 막힌 경우에만 우측으로 선택한다.

arch/system.md

# 시스템 정의

~ 변경 4건합계 4건

구분 | 변경 내용
--- | ---
변경 | SR-03 | 변경 센서가 전방 센서가 장애물을 감지하면 청소를 멈추고, 좌/우로 방향을 틀어 청소하며 전진한다
변경 | 장애물 센서 | 입력 | 변경 전방/좌/우 장애물 감지 신호 전방·좌측 장애물 감지 신호 (우측 전용 센서 없음, 우측 감지는 전방 센서 회전 스캔으로 대체)
변경 | 장애물 회피 (측면 여유 있음): 전방 장애물 감지 → 청소 정지 → 변경 좌 또는 우로 회전 좌측 우선으로 회전 (좌측이 막힌 경우에만 우측) → 청소 재개 및 전진.
변경 | 장애물 회피 (삼면 막힘): 전/좌/우 장애물 모두 감지 → 후진 → 변경 좌 또는 우로 회전 좌측 우선으로 회전 (좌측이 막힌 경우에만 우측) → 전진.

arch/usecases/usecases.md

# Use Case 목록

~ 변경 4건합계 4건

구분 | 변경 내용
--- | ---
변경 | ObstacleSensor | Primary Actor | 변경 전방/좌/우 장애물 감지 신호를 시스템에 전달한다 전방/좌 장애물 감지 신호를 시스템에 전달한다. 우측 장애물 감지는 전방 센서 회전 스캔으로 대체한다 (우측 전용 센서 없음).
변경 | UC-003 | 삼면 장애물 후진 회피 | 변경 ObstacleSensor, DriveMotor ObstacleSensor, DriveMotor, CleaningMotor | FR-03
변경 | 전방에 장애물이 감지되면 청소를 일시 정지하고, 변경 좌 또는 우 중 여유 공간이 있을 때 sideStatus(LEFT) 및 rotateRight() + sideStatus(RIGHT) 로 양측을 순차 확인한다. 변경 좌·우 모두 여유 있으면 랜덤으로 방향을 선택한다. 좌측을 우선으로 선택한다. 좌측이 막힌 경우에만 우측으로 선택한다. 좌·우 모두 막힌 경우 E1으로 UC-003에 진입한다.
변경 | 변경 전방·좌·우 모두 장애물이 감지될 때 ObstacleSensor가 직접 트리거한다. UC-002 E1에서 진입한다 (sideStatus(LEFT, blocked) + sideStatus(RIGHT, blocked) 내부 판정). 후진하며 sideStatus(LEFT) 또는 rotateRight() + sideStatus(RIGHT)로 여유 공간을 확인하고, 확보되면 변경 랜덤으로 좌측을 우선으로 선택하여 회전하고 전진한다.

arch/usecases/UC-001.md

# UC-001: 자동 청소 수행

✕ 삭제 1건~ 변경 1건합계 2건

구분 | 변경 내용
--- | ---
변경 | EP-1 | 변경 frontObstacleDetected AND (좌 OR 우 여유 있음) frontObstacleDetected (좌·우 여유 공간 확인은 UC-002 내에서 sideStatus(LEFT) → rotateRight() + sideStatus(RIGHT) 순으로 수행) | UC-002
삭제 | 삭제 EP-2 | | UC-003 (UC-002 E1 예외 흐름으로 이동)

arch/usecases/UC-002.md

# UC-002: 측면 장애물 회피

✚ 추가 3건~ 변경 8건합계 11건

구분 | 변경 내용
--- | ---
변경 | 변경 좌 또는 우 중 하나 이상의 방향에 여유 공간이 있다. 좌·우 여유 공간 여부는 이 UC 내부에서 순차 확인한다 (진입 시점에 미결정).
변경 | 변경 RVC가 장애물이 없는 방향(좌 또는 우)으로 회전한 뒤, 청소를 재개하며 전진하고 있다. (정상) 좌 또는 우로 회전 후 청소를 재개하며 전진한다. / (예외 E1) 좌·우 모두 막힌 경우 UC-003으로 전환한다.
변경 | 4 | ObstacleSensor | 변경 좌측 장애물 유무 신호를 시스템에 전달한다. sideStatus(LEFT, status) — 좌측 센서가 좌측 장애물 유무 신호를 시스템에 전달한다.
추가 | 5 | System | 추가 DriveMotor에 rotateRight()를 명령한다 (전방 센서를 우측으로 회전).
추가 | 6 | ObstacleSensor | 추가 sideStatus(RIGHT, status) — 전방 센서(우측 향함)가 우측 장애물 유무 신호를 시스템에 전달한다.
추가 | 7 | System | 추가 DriveMotor에 rotateLeft()를 명령한다 (정면 복귀). 이후 turn()이 원래 전방 기준으로 동작하도록 보장한다.
변경 | 8 | System | 변경 여유 있는 방향(좌 또는 우)으로 DriveMotor를 회전시킨다. 좌측이 여유 있으면 좌회전한다. 좌측이 막히고 우측이 여유 있으면 우회전한다.
변경 | A1: 변경 좌·우 모두 여유 있을 때 좌측 여유 우선 선택
변경 | 변경 단계 5에서 좌·우 모두 여유 있으면 랜덤으로 방향을 선택하여 회전한다. 단계 7에서 좌측이 여유 있으면 좌측을 우선으로 선택한다. 좌·우 모두 여유 있더라도 항상 좌측을 선택한다.
변경 | E1: 변경 회피 도중 전/좌/우 모두 막힘 좌·우 모두 막힘 확인 후 UC-003 전환
변경 | 변경 단계 5 이전에 삼면이 모두 막힌 것이 감지되면 UC-003으로 전환한다. 단계 7(rotateLeft 정면 복귀) 완료 후 sideStatus(LEFT)와 sideStatus(RIGHT) 모두 막힘이면 UC-003으로 전환한다.

arch/usecases/UC-003.md

# UC-003: 삼면 장애물 후진 회피

✚ 추가 4건~ 변경 7건합계 11건

구분 | 변경 내용
--- | ---
추가 | 액터 | ObstacleSensor (Primary), DriveMotor (Secondary), 추가 CleaningMotor (Secondary)
변경 | 종류 | 변경 Extension of UC-001 (EP-2) Extension of UC-002 (E1)
변경 | 변경 전방·좌·우 방향 모두에 장애물이 감지되었다. UC-002 내에서 sideStatus(LEFT, blocked) 및 sideStatus(RIGHT, blocked) 가 모두 수신되어 좌·우 모두 막힘이 확인되었다 (UC-002 E1). 우측 전용 센서 없음.
변경 | 1 | (UC-002 E1) | 변경 ObstacleSensor: 전방·좌측 장애물 감지 신호를 전달한다. 좌·우 모두 막힘이 확인된 상태로 UC-002 E1에서 진입한다. (CleaningMotor는 UC-002 단계 2에서 이미 정지됨.)
변경 | 3 | ObstacleSensor | 변경 좌측 장애물 유무 신호를 계속 전달한다. sideStatus(LEFT, status) — 좌측 센서가 좌측 장애물 유무 신호를 전달한다.
추가 | 4 | System | 추가 좌측이 여전히 막힌 경우 DriveMotor에 rotateRight()를 명령한다 (전방 센서를 우측으로 회전).
추가 | 5 | ObstacleSensor | 추가 sideStatus(RIGHT, status) — 전방 센서(우측 향함)가 우측 장애물 유무 신호를 전달한다.
추가 | 6 | System | 추가 rotateRight()를 호출한 경우 DriveMotor에 rotateLeft()를 명령한다 (정면 복귀).
변경 | 9 | System | 변경 여유 공간이 확보된 방향(좌 또는 우)으로 DriveMotor를 회전시킨다. 좌측에 여유 공간이 확보된 경우 좌회전한다. 좌측이 막힌 경우에만 우측으로 DriveMotor를 회전시킨다.
변경 | A1: 변경 후진 중 좌·우 동시에 여유 공간 확보 후진 중 좌측 여유 공간 우선 선택
변경 | 변경 단계 5에서 좌·우 모두 동시에 해소되면 랜덤으로 방향을 선택하여 회전한다. 단계 3에서 sideStatus(LEFT, clear)가 수신되면 단계 4~6을 건너뛰고 즉시 좌회전한다. 좌·우 모두 동시에 확보되더라도 항상 좌측을 우선으로 선택한다.

arch/analysis/ssd/SSD-002.md

# SSD-002: 측면 장애물 회피

✚ 추가 2건~ 변경 1건합계 3건

구분 | 변경 내용
--- | ---
변경 | 변경 `sideStatus(available)` `sideStatus(LEFT, status)` | 변경 여유 공간이 있는 방향(Direction)의 목록을 수신한다 좌측 센서가 좌측 장애물 유무 신호를 전달한다. 회전 없이 직접 수신.
추가 | 추가 `sideStatus(RIGHT, status)` | DriveMotor.rotateRight() 이후 전방 센서(우측 향함)가 우측 장애물 유무 신호를 전달한다 (우측 전용 센서 없음).
추가 | 추가 `rotateLeft()` | sideStatus(RIGHT) 수신 후 DriveMotor를 정면으로 복귀시킨다. 이후 turn()이 항상 원래 전방 기준으로 동작하도록 보장한다.

arch/analysis/ssd/SSD-003.md

# SSD-003: 삼면 장애물 후진 회피

✚ 추가 2건✕ 삭제 1건~ 변경 1건합계 4건

구분 | 변경 내용
--- | ---
삭제 | 삭제 UC-002 내에서 sideStatus(LEFT) + sideStatus(RIGHT) 결과로 내부 판정 후 UC-003에 직접 진입. 별도 외부 오퍼레이션 없음.
변경 | 변경 `sideStatus(available)` `sideStatus(LEFT, status)` | 변경 후진 중 좌·우 여유 공간 목록 수신 후진 중 좌측 센서가 좌측 장애물 유무를 전달한다. 반복 수신.
추가 | 추가 `sideStatus(RIGHT, status)` | 좌측 막힘 시 rotateRight() 이후 전방 센서(우측 향함)가 우측 장애물 유무를 전달한다. 좌측 여유 확보 시 생략.
추가 | 추가 `rotateLeft()` | 좌측 막힘 시 sideStatus(RIGHT) 수신 후 DriveMotor를 정면으로 복귀시킨다. 루프 재진입 및 최종 turn() 모두 원래 전방 기준으로 동작하도록 보장한다.

arch/analysis/domain/domain.md

# 도메인 모델

✚ 추가 1건✕ 삭제 1건~ 변경 4건합계 6건

구분 | 변경 내용
--- | ---
변경 | 센서 데이터는 시스템 오퍼레이션의 파라미터로 전달된다. 변경 `sideStatus(available)` 좌·우 각각 `sideStatus(LEFT, status)` / `sideStatus(RIGHT, status)` 두 번의 별도 호출로 분리된다. 우측은 `rotateRight()` 이후 전방 센서가 전달한다.
변경 | ObstacleSensor | 변경 장애물 감지 이벤트를 RVCController에 전달한다 전방·좌측 장애물 감지 이벤트를 RVCController에 전달한다. sideStatus(LEFT)는 좌측 센서가 직접 전달하고, sideStatus(RIGHT)는 DriveMotor.rotateRight() 이후 전방 센서가 전달한다 (우측 전용 센서 없음).
삭제변경 | RVCController | 변경 시스템 오퍼레이션(start, frontObstacleDetected, 삭제, sideStatus, dustDetected)을 수신한다. 시스템 오퍼레이션 (start, frontObstacleDetected, sideStatus(LEFT, status), sideStatus(RIGHT, status), dustDetected)을 수신하고 NavigationController·CleaningController에 위임한다.
추가변경 | NavigationController | DriveMotor를 제어한다. 변경 방향 선택 로직(양쪽 여유 시 랜덤)을 포함한다 방향 선택 로직(좌측 우선; 좌측이 막힌 경우에만 우측)을 포함한다. 추가 `rotateLeft()`로 우측 스캔 후 정면 복귀한다.

arch/design/sd/SD-002.md

# SD-002: 측면 장애물 회피

✚ 추가 2건~ 변경 2건합계 4건

구분 | 변경 내용
--- | ---
변경 | 변경 `NavigationController.turn(available)` — `Direction` 목록을 받아 방향 선택 로직(랜덤 포함)을 NavigationController 내부에서 수행한다 (SRP) `NavigationController.turn(direction: Direction)` — 단일 방향을 받아 회전한다. 방향 선택(좌측 우선)은 RVCController가 두 sideStatus 결과로 결정한 뒤 전달한다.
변경 | 변경 예외 흐름 E1 (좌·우 모두 막힘): `sideStatus([])` 수신 시(available이 빈 리스트) RVCController가 UC-003 흐름으로 전환한다 예외 흐름 E1: sideStatus(LEFT, blocked) AND sideStatus(RIGHT, blocked) 수신 시 RVCController가 UC-003 흐름으로 전환한다.
추가 | 추가 `rotateRight()` — RVCController → NavigationController → DriveMotor 순으로 위임하여 전방 센서를 우측으로 회전시킨다. sideStatus(LEFT) 수신 직후, sideStatus(RIGHT) 수신 직전에 호출한다.
추가 | 추가 `rotateLeft()` — sideStatus(RIGHT) 수신 직후 정면으로 복귀한다. 이후 turn(LEFT)/turn(RIGHT)이 모두 원래 전방 기준으로 대칭 동작하도록 보장한다.

arch/design/sd/SD-003.md

# SD-003: 삼면 장애물 후진 회피

✚ 추가 2건✕ 삭제 1건~ 변경 3건합계 6건

구분 | 변경 내용
--- | ---
변경 | 변경 청소 재개(`startCleaning`)는 전진 시작 이후에 호출한다 (UC-003 기본 흐름 8→9 순서) 청소 재개(`startCleaning`)는 전진(`moveForward`) 이후에 호출한다 (UC-003 기본 흐름 9→10 순서).
변경 | 변경 후진 중 루프를 탈출하는 조건: `available`이 비어 있지 않을 때 후진 중 루프 탈출 조건: sideStatus(LEFT, clear) 또는 sideStatus(RIGHT, clear) 중 하나라도 수신될 때.
변경 | 변경 방향 선택 로직은 SD-002와 동일하게 NavigationController 내부에서 수행한다 방향 선택(좌측 우선)은 RVCController가 sideStatus 결과로 결정하고 NavigationController에 단일 방향을 전달한다.
추가 | 추가 UC-003은 UC-002 E1에서 진입한다. CleaningMotor는 UC-002에서 이미 정지된 상태이므로 이 SD에서 별도의 stopCleaning 호출이 없다.
삭제 | 삭제 `allSidesBlocked()` — ObstacleSensor → RVCController 외부 호출 (UC-002 내 두 sideStatus 결과로 내부 판정)
추가 | 추가 후진 중 좌측이 막혀있을 때만 rotateRight() → sideStatus(RIGHT) → rotateLeft() 순으로 우측을 확인하고 정면 복귀한다. 좌측 clear 시 즉시 좌회전하며 우측 확인을 생략한다.

arch/design/class/class-diagram.md

# 클래스 다이어그램

✚ 추가 10건✕ 삭제 1건~ 변경 6건합계 17건

구분 | 변경 내용
--- | ---
변경 | ObstacleSensor | 변경 `frontObstacleDetected()`, `sideStatus(available)`, `allSidesBlocked()` 이벤트를 전달한다 `frontObstacleDetected()`, `sideStatus(LEFT, status)`, `sideStatus(RIGHT, status)` 이벤트를 전달한다. 우측은 `rotateRight()` 이후 전방 센서가 전달한다 (우측 전용 센서 없음).
변경 | NavigationController | 변경 `IDriveMotor`를 제어한다. `turn(available)`에서 `Direction` 목록을 받아 방향 선택 로직(양쪽 여유 시 랜덤)을 수행한다 `IDriveMotor`를 제어한다. `turn(direction: Direction)`으로 단일 방향을 받아 회전한다. `rotateRight()`로 전방 센서를 우측으로 회전시킨다. 방향 선택(좌측 우선)은 RVCController가 결정한다.
변경 | 변경 `RVCController.sideStatus(available: List<Direction>)` `RVCController.sideStatus(direction: Direction, status: bool)` | SD-002, SD-003
삭제 | 삭제 `RVCController.allSidesBlocked()` | SD-003
변경 | 변경 `NavigationController.turn(available: List<Direction>)` `NavigationController.turn(direction: Direction)` | SD-002, SD-003
추가 | 추가 `NavigationController.rotateRight()` | SD-002, SD-003
추가 | 추가 `IDriveMotor.rotateRight()` | SD-002, SD-003
추가 | 추가 `NavigationController.rotateLeft()` | SD-002, SD-003
추가 | 추가 `IDriveMotor.rotateLeft()` | SD-002, SD-003
추가 | 추가 다이어그램: `RVCController.dustDetected(dustLevel: float)` — 음수 입력 시 무시하는 오버로드 | —
추가 | 추가 다이어그램: `RVCController.changeState(newState: int)` — 유효 범위 외·동일 상태 전이 무시 | —
추가 | 추가 다이어그램: `CleaningController.normalizePower()` — BOOST → NORMAL 즉시 복귀 | —
변경 | 변경 RVCController 클래스 책임 요약 — 추가 `dustDetected(float)`: 음수 입력 시 무시하는 오버로드. 추가 `changeState(int)`: 0(IDLE)/1(CLEANING) 범위 외 값 및 동일 상태 전이 무시
변경 | 변경 CleaningController 클래스 책임 요약 — 추가 `normalizePower()`: BOOST 상태에서 즉시 NORMAL로 복귀(비활성 및 비부스트 상태 시 무시)
추가 | 추가 메서드 출처: `RVCController.dustDetected(float dustLevel)` | — (음수 입력 무시 오버로드, 시나리오 테스트 지원)
추가 | 추가 메서드 출처: `RVCController.changeState(int newState)` | — (유효 범위 외·동일 상태 전이 무시, 시나리오 테스트 지원)
추가 | 추가 메서드 출처: `CleaningController.normalizePower()` | — (BOOST → NORMAL 즉시 복귀, 시나리오 테스트 지원)

src/code.md

# src/ 코드 변경 이력

✚ 추가 23건✕ 삭제 5건~ 변경 15건합계 43건

구분 | 파일 / 항목 | 내용
--- | --- | ---
추가 | `IDriveMotor.hpp` | 추가 `rotateRight() = 0` — 전방 센서를 우측으로 회전시키기 위한 순수 가상 메서드 추가
추가 | `IDriveMotor.hpp` | 추가 `rotateLeft() = 0` — 우측 스캔 후 정면으로 복귀하기 위한 순수 가상 메서드 추가
삭제 | `NavigationController.hpp` | 삭제 `#include <vector>` — `turn()` 시그니처 변경으로 vector 불필요
변경 | `NavigationController.hpp` | 변경 `turn(const std::vector<Direction>&)` → `turn(Direction direction)` — 단일 방향 인자로 단순화
추가 | `NavigationController.hpp` | 추가 `rotateRight()` — IDriveMotor::rotateRight() 위임 메서드
추가 | `NavigationController.hpp` | 추가 `rotateLeft()` — IDriveMotor::rotateLeft() 위임 메서드
추가 | `NavigationController.hpp` | 추가 `MotorState` enum — 모터 상태 추적을 위한 내부 열거형 (STOPPED, FORWARD, BACKWARD, LEFT, RIGHT, ROTATING_RIGHT, ROTATING_LEFT)
추가 | `NavigationController.hpp` | 추가 `MotorState motorState_` — 현재 모터 상태 멤버 변수 (초기값 STOPPED)
삭제 | `NavigationController.cpp` | 삭제 `#include <vector>`, `#include <random>` — 랜덤 선택 로직 제거로 헤더 불필요
변경 | `NavigationController.cpp` | 변경 `turn()` 구현 — 벡터를 받아 랜덤으로 방향 선택 → 단일 방향을 `motor_.turn(direction)`에 위임. 중복 호출 및 FORWARD/BACKWARD 중 전환 시도를 거부하는 MotorState guard 추가
추가 | `NavigationController.cpp` | 추가 `rotateRight()` 구현 — `motor_.rotateRight()` 위임
추가 | `NavigationController.cpp` | 추가 `rotateLeft()` 구현 — `motor_.rotateLeft()` 위임
변경 | `NavigationController.cpp` | 변경 `moveForward()` 구현 — 이미 FORWARD 상태면 중복 호출 무시 (MotorState guard)
변경 | `NavigationController.cpp` | 변경 `moveBackward()` 구현 — 이미 BACKWARD 상태면 중복 호출 무시 (MotorState guard)
변경 | `NavigationController.cpp` | 변경 `stop()` 구현 — 이미 STOPPED 상태면 중복 호출 무시 (MotorState guard)
추가 | `CleaningController.hpp` | 추가 `normalizePower()` — BOOST → NORMAL 강제 복귀 (비활성·비부스트 상태 시 무시)
추가 | `CleaningController.hpp` | 추가 `bool active_` — 청소 활성화 여부 추적 멤버 변수 (초기값 false)
변경 | `CleaningController.cpp` | 변경 `startCleaning()` — 이미 활성 상태(`active_==true`)면 중복 호출 무시. `active_=true` 설정 추가
변경 | `CleaningController.cpp` | 변경 `stopCleaning()` — 비활성 상태(`active_==false`)면 중복 호출 무시. `active_=false` 설정 추가
변경 | `CleaningController.cpp` | 변경 `boostCleaning()` — 비활성 상태(`active_==false`)면 호출 거부
추가 | `CleaningController.cpp` | 추가 `normalizePower()` 구현 — 비활성 또는 비부스트 상태면 무시. 활성+부스트 중일 때 타이머 중단 후 NORMAL 복귀
삭제 | `RVCController.hpp` | 삭제 `#include <vector>` — `sideStatus()` 시그니처 변경으로 불필요
삭제 | `RVCController.hpp` | 삭제 `void allSidesBlocked()` — 전방·좌·우 동시 막힘 판정을 `sideStatus()` 내부 상태머신으로 대체
변경 | `RVCController.hpp` | 변경 `sideStatus(const std::vector<Direction>&)` → `sideStatus(Direction direction, bool clear)` — 방향별 상태를 순차 호출로 분리
변경 | `RVCController.hpp` | 변경 `State` enum — `IDLE`, `CLEANING`, `REVERSING` 3개 → 6개 상태로 확장
추가 | `RVCController.hpp` | 추가 `State::STOPPED` — `frontObstacleDetected()` 수신 후 좌측 스캔 대기 상태
추가 | `RVCController.hpp` | 추가 `State::STOPPED_CHECKING_RIGHT` — `sideStatus(LEFT)` 수신 후 `rotateRight()` 호출, 우측 스캔 대기 상태
추가 | `RVCController.hpp` | 추가 `State::REVERSING_CHECKING_RIGHT` — 후진 중 `sideStatus(LEFT)` 막힘 확인 후 `rotateRight()`, 우측 스캔 대기 상태
추가 | `RVCController.hpp` | 추가 `bool leftClear_` — `STOPPED` → `STOPPED_CHECKING_RIGHT` 전이 시 좌측 결과 임시 보관
추가 | `RVCController.hpp` | 추가 `dustDetected(float dustLevel)` — 먼지 수준 float 파라미터 오버로드. 음수 입력 시 무시
추가 | `RVCController.hpp` | 추가 `changeState(int newState)` — 외부에서 상태 직접 지정 (0=IDLE, 1=CLEANING). 범위 외 값 및 동일 상태 전이 무시
삭제 | `RVCController.cpp` | 삭제 `allSidesBlocked()` 구현 — 좌·우 모두 막힘은 `STOPPED_CHECKING_RIGHT` 상태에서 내부 판정
변경 | `RVCController.cpp` | 변경 `sideStatus()` 시그니처 — `const std::vector<Direction>&` → `Direction direction, bool clear`
변경 | `RVCController.cpp` | 변경 `sideStatus()` 내부 로직 — 방향 목록 기반 단순 분기 → 4개 상태에 걸친 순차 상태머신으로 전면 재작성
추가 | `RVCController.cpp` | 추가 `STOPPED` 분기 — `leftClear_` 저장 후 `rotateRight()` 호출, `STOPPED_CHECKING_RIGHT` 전이
추가 | `RVCController.cpp` | 추가 `STOPPED_CHECKING_RIGHT` 분기 — `rotateLeft()` 정면 복귀 후 LEFT 우선 방향 결정. 양쪽 막힘 시 `moveBackward()` → `REVERSING`
추가 | `RVCController.cpp` | 추가 `REVERSING` 분기 — 좌측 여유 시 즉시 `stop+turn(LEFT)+forward`. 막힘 시 `rotateRight()` → `REVERSING_CHECKING_RIGHT`
추가 | `RVCController.cpp` | 추가 `REVERSING_CHECKING_RIGHT` 분기 — `rotateLeft()` 복귀 후 우측 여유 시 `stop+turn(RIGHT)+forward`. 막힘 시 `REVERSING` 복귀(계속 후진)
변경 | `RVCController.cpp` | 변경 `start()` 구현 — CLEANING·REVERSING·REVERSING_CHECKING_RIGHT 상태에서 중복 호출 무시 guard 추가
변경 | `RVCController.cpp` | 변경 `frontObstacleDetected()` 구현 — REVERSING·REVERSING_CHECKING_RIGHT 상태(후진 중)에서 재감지 무시 guard 추가
추가 | `RVCController.cpp` | 추가 `dustDetected(float)` 구현 — 음수(`< 0.0f`) 입력 시 무시. 그 외 `cleaning_.boostCleaning()` 위임
추가 | `RVCController.cpp` | 추가 `changeState(int)` 구현 — 유효 범위(0~1) 외 및 동일 상태 전이 무시. 0=IDLE, 1=CLEANING으로 직접 `state_` 설정

tests/unit_test.md

# 단위 테스트 변경 이력

✚ 추가 33건✕ 삭제 15건~ 변경 5건합계 53건

구분 | 파일 / 테스트명 | 변경 내용
--- | --- | ---
변경 | `CleaningControllerTest.cpp` `stopCleaning_callsMotorStop` | 변경 `controller.startCleaning()` 선행 호출 추가 — `active_`: false → true
변경 | `CleaningControllerTest.cpp` `boostCleaning_whenIdle_switchesToHighLevel` | 변경 `controller.startCleaning()` 및 `motor.startCalls.clear()` 선행 추가
변경 | `CleaningControllerTest.cpp` `timerExpiry_restoresNormal_andAllowsSubsequentBoost` | 변경 `controller.startCleaning()` 선행 호출 추가
변경 | `CleaningControllerTest.cpp` `boostCleaning_whenAlreadyBoosting_doesNotCallMotorAgain` | 변경 `controller.startCleaning()` 선행 추가 — `active_==false`로 인해 `timer_.reset()` 분기 미도달 수정, 라인 커버리지 100% 달성
추가 | `CleaningControllerTest.cpp` `normalizePower_whenBoosting_restoresNormal` | 추가 부스트 중 `normalizePower()` → NORMAL 복귀 및 모터 호출 확인
추가 | `CleaningControllerTest.cpp` `normalizePower_whenNotBoosting_isIgnored` | 추가 비부스트 상태에서 `normalizePower()` 무시 — 모터 재호출 없음
추가 | `CleaningControllerTest.cpp` `normalizePower_whenInactive_isIgnored` | 추가 비활성(`active_==false`) 상태에서 `normalizePower()` 무시
삭제 | `NavigationControllerTest.cpp` `turn_emptyList_doesNotCallMotor` | 삭제 벡터 기반 — 빈 목록 시 모터 미호출 검증. 시그니처 변경으로 삭제
삭제 | `NavigationControllerTest.cpp` `turn_singleLeft_turnsLeft` | 삭제 벡터 기반 단일 LEFT 검증. 단일 방향 기반으로 대체
삭제 | `NavigationControllerTest.cpp` `turn_singleRight_turnsRight` | 삭제 벡터 기반 단일 RIGHT 검증. 단일 방향 기반으로 대체
삭제 | `NavigationControllerTest.cpp` `turn_multipleDirections_picksExactlyOne` | 삭제 랜덤 방향 선택 검증. v2.0 랜덤 로직 제거로 삭제
삭제 | `NavigationControllerTest.cpp` `turn_calledTwice_motorCalledTwice` | 삭제 2회 연속 turn 검증. MotorState guard 도입으로 동작 변경되어 삭제
추가 | `NavigationControllerTest.cpp` `turn_left_delegatesToMotor` | 추가 `turn(Direction::LEFT)` 단일 방향 위임 검증
추가 | `NavigationControllerTest.cpp` `turn_right_delegatesToMotor` | 추가 `turn(Direction::RIGHT)` 단일 방향 위임 검증
추가 | `NavigationControllerTest.cpp` `rotateRight_delegatesToMotor` | 추가 `rotateRight()` → 모터 위임 검증
추가 | `NavigationControllerTest.cpp` `rotateLeft_delegatesToMotor` | 추가 `rotateLeft()` → 모터 위임 검증
변경 | `NavigationControllerTest.cpp` `stop_delegatesToMotor` | 변경 `controller.moveForward()` 선행 추가 — `motorState_`: STOPPED → FORWARD
삭제 | `RVCControllerTest.cpp` `sideStatus_whenStopped_turnsToAvailableDirection` | 삭제 벡터 기반 시그니처 → 방향별 2단계 호출로 대체
삭제 | `RVCControllerTest.cpp` `sideStatus_whenStopped_restartsCleaning` | 삭제 벡터 기반 시그니처 → 방향별 2단계 호출로 대체
삭제 | `RVCControllerTest.cpp` `sideStatus_whenStopped_movesForward` | 삭제 벡터 기반 시그니처 → 방향별 2단계 호출로 대체
삭제 | `RVCControllerTest.cpp` `allSidesBlocked_stopsCleaning` | 삭제 `allSidesBlocked()` 오퍼레이션 삭제에 따라 제거
삭제 | `RVCControllerTest.cpp` `allSidesBlocked_movesBackward` | 삭제 `allSidesBlocked()` 오퍼레이션 삭제에 따라 제거
삭제 | `RVCControllerTest.cpp` `sideStatus_whenReversing_withAvailableDir_stopsMotor` | 삭제 벡터 기반 — 좌측 우선 로직으로 전면 재작성
삭제 | `RVCControllerTest.cpp` `sideStatus_whenReversing_withAvailableDir_turns` | 삭제 벡터 기반 — 좌측 우선 로직으로 전면 재작성
삭제 | `RVCControllerTest.cpp` `sideStatus_whenReversing_withAvailableDir_movesForward` | 삭제 벡터 기반 — 좌측 우선 로직으로 전면 재작성
삭제 | `RVCControllerTest.cpp` `sideStatus_whenReversing_withAvailableDir_restartsCleaning` | 삭제 벡터 기반 — 좌측 우선 로직으로 전면 재작성
삭제 | `RVCControllerTest.cpp` `sideStatus_whenReversing_withEmptyDir_isIgnored` | 삭제 벡터 기반 — 좌측 우선 로직으로 전면 재작성
추가 | `RVCControllerTest.cpp` `sideStatus_firstCall_rotatesRight` | 추가 STOPPED 상태에서 첫 `sideStatus(LEFT)` 수신 시 `rotateRight()` 호출
추가 | `RVCControllerTest.cpp` `sideStatus_secondCall_rotatesLeft` | 추가 STOPPED_CHECKING_RIGHT에서 `sideStatus(RIGHT)` 수신 시 `rotateLeft()` 호출
추가 | `RVCControllerTest.cpp` `sideStatus_leftClear_turnsLeft` | 추가 좌측 여유 시 LEFT 방향으로 회전
추가 | `RVCControllerTest.cpp` `sideStatus_leftClear_restartsCleaning` | 추가 좌측 여유 시 청소 재개
추가 | `RVCControllerTest.cpp` `sideStatus_leftClear_movesForward` | 추가 좌측 여유 시 전진
추가 | `RVCControllerTest.cpp` `sideStatus_leftBlockedRightClear_turnsRight` | 추가 좌측 막힘·우측 여유 시 RIGHT 방향으로 회전
추가 | `RVCControllerTest.cpp` `sideStatus_leftBlockedRightClear_restartsCleaning` | 추가 좌측 막힘·우측 여유 시 청소 재개
추가 | `RVCControllerTest.cpp` `sideStatus_leftBlockedRightClear_movesForward` | 추가 좌측 막힘·우측 여유 시 전진
추가 | `RVCControllerTest.cpp` `sideStatus_bothBlocked_movesBackward` | 추가 좌우 모두 막힘 시 후진 (E1 진입)
추가 | `RVCControllerTest.cpp` `sideStatus_bothBlocked_doesNotTurn` | 추가 좌우 모두 막힘 시 `turn` 미호출
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_leftClear_stops` | 추가 후진 중 좌측 여유 시 `stop`
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_leftClear_turnsLeft` | 추가 후진 중 좌측 여유 시 LEFT 회전
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_leftClear_movesForward` | 추가 후진 중 좌측 여유 시 전진
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_leftClear_restartsCleaning` | 추가 후진 중 좌측 여유 시 청소 재개
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_leftBlocked_rotatesRight` | 추가 후진 중 좌측 막힘 시 `rotateRight()` 호출
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_rightOnly_turnsRight` | 추가 후진 중 우측만 여유 시 RIGHT 회전
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_rightOnly_movesForward` | 추가 후진 중 우측만 여유 시 전진
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_rightOnly_restartsCleaning` | 추가 후진 중 우측만 여유 시 청소 재개
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_bothBlocked_noTurnOrForward` | 추가 후진 중 좌우 모두 막힘 시 `turn`/`forward` 미호출
추가 | `RVCControllerTest.cpp` `sideStatus_whenReversing_bothBlocked_rotatesRightThenLeft` | 추가 후진 중 좌우 막힘 시 `rotateRight` → `rotateLeft` 호출
추가 | `RVCControllerTest.cpp` `dustDetected_positiveLevel_boostsCleaning` | 추가 `dustDetected(float)` 양수 입력 → HIGH 전환 확인
추가 | `RVCControllerTest.cpp` `dustDetected_negativeLevel_isIgnored` | 추가 `dustDetected(float)` 음수 입력 → 무시, 모터 미호출
추가 | `RVCControllerTest.cpp` `changeState_idleToCleaning_changesState` | 추가 `changeState(1)` → CLEANING 전이 후 `start()` 중복 무시 확인
추가 | `RVCControllerTest.cpp` `changeState_cleaningToIdle_changesState` | 추가 `changeState(0)` → IDLE 전이 후 `start()` 정상 동작 확인
추가 | `RVCControllerTest.cpp` `changeState_outOfRange_isIgnored` | 추가 범위 외 값(999, -1) 입력 시 상태 변화 없음
추가 | `RVCControllerTest.cpp` `changeState_sameState_isIgnored` | 추가 동일 상태 전이 무시 — 모터 재호출 없음

system-tests/system_test.md

# 시스템 테스트 변경 이력

✚ 추가 2건합계 2건

구분 | 파일 | 내용
--- | --- | ---
추가 | `SystemTests.cpp` | 추가 v2.0 핵심 시나리오 30개 (긍정 ST-P01~P10 · 부정 ST-N01~N20). v1.0에 시스템 테스트 없음 — v2.0 신규 작성.
추가 | `SystemTests_v2.cpp` | 추가 UP팀 제공 시나리오 30개 (긍정 TC-POS-01~10 · 부정 TC-NEG-01~20). v1.0에 시스템 테스트 없음 — v2.0 신규 작성.